import * as request from "superagent";
import { SuperAgentStatic } from "superagent";


type CallbackHandler = (err: any, res?: request.Response) => void;
interface IUserModel {
    'user_id'?: string;

    'username': string;

}

interface ILogger { log: (line: string) => any };

/**
 * The Open Api Service
 * @class Test
 * @param {(string)} [domainOrOptions] - The project domain.
 */
export default class Test {

    private domain: string = "";
    private errorHandlers: CallbackHandler[] = [];

    constructor(domain?: string, private logger?: ILogger) {
        if (domain) {
            this.domain = domain;
        }
    }





    public get_user_listURL(parameters: {
        'xFields'?: string
        ,
        $queryParameters?: any,
        $domain?: string
    }): string {
        const queryParameters: any = {};
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        const path = '/users';


        if (parameters.$queryParameters) {
            Object.keys(parameters.$queryParameters).forEach((parameterName) => {
                queryParameters[parameterName] = parameters.$queryParameters[parameterName];
            });
        }



        const keys = Object.keys(queryParameters);
        return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '');
    }

    /**
     * eee
     * @method
     * @name Test#get_user_list
     * @param {string} xFields - An optional fields mask
     */
    public get_user_list(parameters: {
        'xFields'?: string
        ,
        $queryParameters?: any,
        $domain?: string
    }): Promise<request.Response> {
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        const path = '/users';
        const body: any = undefined;
        const queryParameters: any = {};
        const headers: any = {};
        const form: any = {};
        return new Promise((resolve, reject) => {
            headers['Accept'] = 'application/json';
            headers['Content-Type'] = 'application/json';

            if (parameters['xFields'] !== undefined) {
                headers['X-Fields'] = parameters['xFields'];
            }





            if (parameters.$queryParameters) {
                Object.keys(parameters.$queryParameters).forEach((parameterName) => {
                    queryParameters[parameterName] = parameters.$queryParameters[parameterName];
                });
            }


            this.request('GET', domain + path, body, headers, queryParameters, form, reject, resolve);

        });
    }

    public create_userURL(parameters: {
        'payload': IUserModel
        ,
        'xFields'?: string
        ,
        $queryParameters?: any,
        $domain?: string
    }): string {
        let queryParameters: any = {};
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        let path = '/users';



        if (parameters.$queryParameters) {
            Object.keys(parameters.$queryParameters).forEach((parameterName) => {
                queryParameters[parameterName] = parameters.$queryParameters[parameterName];
            });
        }

        queryParameters = {};


        let keys = Object.keys(queryParameters);
        return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '');
    }

    /**
     * 
     * @method
     * @name Test#create_user
     * @param {} payload - The Open Api Service
     * @param {string} xFields - An optional fields mask
     */
    public create_user(parameters: {
        'payload': IUserModel
        ,
        'xFields'?: string
        ,
        $queryParameters?: any,
        $domain?: string
    }): Promise<request.Response> {
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        let path = '/users';
        let body: any;
        let queryParameters: any = {};
        let headers: any = {};
        let form: any = {};
        return new Promise((resolve, reject) => {
            headers['Accept'] = 'application/json';
            headers['Content-Type'] = 'application/json';





            if (parameters['payload'] !== undefined) {
                body = parameters['payload'];
            }


            if (parameters['payload'] === undefined) {
                reject(new Error('Missing required  parameter: payload'));
                return;
            }




            if (parameters['xFields'] !== undefined) {
                headers['X-Fields'] = parameters['xFields'];
            }





            if (parameters.$queryParameters) {
                Object.keys(parameters.$queryParameters).forEach((parameterName) => {
                    queryParameters[parameterName] = parameters.$queryParameters[parameterName];
                });
            }

            form = queryParameters;
            queryParameters = {};

            this.request('POST', domain + path, body, headers, queryParameters, form, reject, resolve);
        });
    }
    private request(method: string, url: string, body: any, headers: any, queryParameters: any, form: any, reject: CallbackHandler, resolve: CallbackHandler) {
        if (this.logger) {
            this.logger.log(`Call ${method} ${url}`);
        }

        const req = (request as SuperAgentStatic)(method, url).query(queryParameters);

        Object.keys(headers).forEach(key => {
            req.set(key, headers[key]);
        });

        if (body) {
            req.send(body);
        }

        if (typeof (body) === 'object' && !(body.constructor.name === 'Buffer')) {
            req.set('Content-Type', 'application/json');
        }

        if (Object.keys(form).length > 0) {
            req.type('form');
            req.send(form);
        }
        req.withCredentials().end((error, response) => {
            console.log(error);
            if (error || !response.ok) {
                reject(error);
                this.errorHandlers.forEach(handler => handler(error));
            } else {
                resolve(response);
            }
        });
    }

}

